#include "keycontrollablemenu.h"
#include "playermanager.h"

VolumeDisplay * KeyControllableMenu::volumeDisplay;

KeyControllableMenu::KeyControllableMenu(QWidget * parent) : QWidget(parent)
{
    setMouseTracking(true);
    rows=new QList<ButtonList *>;
    active=true;
    setStyleSheet("color: white");
    //KeyBindings::loadKeyBindings();
    currentRow=0;
    currentColumn=0;
    unSelectedStyleSheet="border: 1px solid rgba(255, 255, 255, 0); border-radius: 10px; color: rgba(255,255,255,255);";
    //selectedStyleSheet="QPushButton { background: qlineargradient(spread:pad, x1:0.07, y1:0.153409, x2:1, y2:1, stop:0 rgba(0, 0, 0, 255), stop:1 rgba(0, 100, 129, 255)); border: 1px solid rgba(255, 255, 255, 70); border-radius: 10px;  }";
    selectedStyleSheet="QPushButton { background: qlineargradient(spread:pad, x1:0.07, y1:0.153409, x2:1, y2:1, stop:0 rgba(0, 0, 0, 50), stop:1 rgba(255, 255, 255, 70)); border: 1px solid rgba(255, 255, 255, 200); border-radius: 10px;  }";
    //inactiveSelectedStyleSheet="border:0px; background-color: grey; color: white; font-size 40px;";
    inactiveSelectedStyleSheet="background: qlineargradient(spread:pad, x1:0.07, y1:0.153409, x2:1, y2:1, stop:0 rgba(255, 255, 255, 100), stop:1 rgba(255, 255, 255, 200)); border: 1px solid rgba(255, 255, 255, 200); border-radius: 10px;";
    setMouseTracking(true);
    isCircularHorizontally=false;
    isCircularVertically=true;
}

void KeyControllableMenu::addRow(QList<Button *> * buttons) {
    rows->append(buttons);
    foreach(Button * button, *buttons) {
        button->setStyleSheet(unSelectedStyleSheet);
        button->setMouseTracking(true);
        connect(button, SIGNAL(mouseEntered(Button*)), this, SLOT(buttonEntered(Button*)));
        connect(button, SIGNAL(clicked()), this,  SLOT(buttonSelected()));
        connect(button,SIGNAL(rightClicked()),this,SLOT(buttonRightClicked()));
        //button->setFlat(true);
    }
    if(rows->size()==1) {
        currentRow=0;
        currentColumn=0;
        setActive(rows->at(0)->at(0));
    }
}

void KeyControllableMenu::addRow(Button *button) {
    QList<Button *> * buttons=new QList<Button *>();
    buttons->append(button);
    addRow(buttons);
}

void KeyControllableMenu::buttonEntered(Button * button) {
    if(!active) {
        return;
    }
    if(getCurrentButton()) {
        if(getCurrentButton()->styleSheet()!=inactiveSelectedStyleSheet) {
            setActive(button);
        }
    }
}

void KeyControllableMenu::buttonSelected() {

}

void KeyControllableMenu::setActive(Button * button) {
    for(int i=0; i<rows->size(); i++) {
        for(int j=0; j<rows->at(i)->size(); j++) {
            if(button==rows->at(i)->at(j)) {
                if(currentRow>=0) {
                    if(rows->size()>currentRow) {
                        rows->at(currentRow)->at(currentColumn)->setStyleSheet(unSelectedStyleSheet);
                    }
                    //current->setStyleSheet(unSelectedButtonStyleSheet);
                    //rows->at(currentRow)->at(currentColumn)->setFlat(true);
                }
                currentRow=i;
                currentColumn=j;
                rows->at(i)->at(j)->setStyleSheet(selectedStyleSheet);
                //rows->at(i)->at(j)->setFlat(false);
                return;
            }
        }
    }
}


void KeyControllableMenu::keyPressEvent ( QKeyEvent * event ) {
    qDebug() <<"key pressed "<<event->key()<<" with modifiers "<<event->modifiers();
    if(event->key()==KeyBindings::volumeDownKey[0]&&event->modifiers()==KeyBindings::volumeDownKey[1]) {
        volumeDisplay->decreaseVolume();
    }
    else if(KeyBindings::matchesKeys(KeyBindings::volumeUpKey,event)) {
        volumeDisplay->increaseVolume();
    }


    if(KeyBindings::matchesKeys(KeyBindings::selectKey,event)) {
        //calling the method directly doesn't activate the child's method for some reason
        QTimer::singleShot(10, this, SLOT(buttonSelected()));
     } else if(KeyBindings::matchesKeys(KeyBindings::secondaryKey,event)) {
        QTimer::singleShot(10, this, SLOT(buttonRightClicked()));
     }else if(!rows||rows->size()==0) {
         return;
     } else if(KeyBindings::matchesKeys(KeyBindings::upKey,event)) {
         qDebug()<<currentRow;
         qDebug()<<"going up";
        if(currentRow==0) {
            qDebug() <<isCircularVertically;
            if(isCircularVertically) {
                setActive(rows->at(rows->size()-1)->at(0));
            } else {
                emit escapeTop();
            }
        } else {
            setActive(rows->at(currentRow-1)->at(0));
        }
    } else if(KeyBindings::matchesKeys(KeyBindings::downKey,event)) {
        qDebug()<<currentRow<<" "<<rows->size()<<" "<<rows->count();
        if(currentRow+1>=rows->size()) {

            if(isCircularVertically) {
                setActive(rows->at(0)->at(0));
            } else {
                emit escapeBottom();
            }
        } else {
            qDebug()<<"activating "<<currentRow+1;
            setActive(rows->at(currentRow+1)->at(0));
        }
    }  else if(KeyBindings::matchesKeys(KeyBindings::rightKey,event)) {
        if(currentColumn+1==rows->at(currentRow)->size()) {
            if(isCircularHorizontally) {
                setActive(rows->at(currentRow)->at(0));
            } else {
                emit escapeRight();
            }
        } else {
            setActive(rows->at(currentRow)->at(currentColumn+1));
        }
    } else if(KeyBindings::matchesKeys(KeyBindings::leftKey,event)) {
        if(currentColumn==0) {
            if(isCircularHorizontally) {
                qDebug() <<"moving to row "<<QString::number(rows->at(currentRow)->size()-1);
                setActive(rows->at(currentRow)->at(rows->at(currentRow)->size()-1));
            } else {
                emit escapeLeft();
            }
        } else {
            setActive(rows->at(currentRow)->at(currentColumn-1));
        }
    } else if(KeyBindings::matchesKeys(KeyBindings::nowPlayingKey,event)) {
        WindowManager::goToNowPlaying();
    } else if(KeyBindings::matchesKeys(KeyBindings::backKey,event)) {
        WindowManager::goBack();
    } else if(KeyBindings::matchesKeys(KeyBindings::homeKey,event)) {
        WindowManager::goHome();
    }
    else {
        //emit keyPressed(event);
    }
    PlayerManager::interpretKeys(event);
}

void KeyControllableMenu::removeButton(Button * button) {
    for(int i=0; i<rows->size(); i++) {
        ButtonList * buttons = rows->at(i);
        if(buttons->contains(button)) {
            for(int j=0; j<buttons->size(); j++) {
                disconnect(buttons->at(j), SIGNAL(mouseEntered(Button*)), this, SLOT(buttonEntered(Button*)));
                disconnect(buttons->at(j), SIGNAL(clicked()), this,  SLOT(buttonSelected()));
                disconnect(buttons->at(j),SIGNAL(rightClicked()),this,SLOT(buttonRightClicked()));
                buttons->at(j)->setStyleSheet(unSelectedStyleSheet);
            }
            if(i==currentRow&&currentColumn==buttons->indexOf(button)) {
                if(rows->size()>currentRow+1) {
                    rows->removeAt(i);
                    setActive(rows->at(currentRow)->at(0));
                } else if(i>0) {
                    rows->removeAt(i);
                    setActive(rows->at(currentRow-1)->at(0));
                } else {
                    rows->clear();
                }
            } else if(i<currentRow) {
                rows->removeAt(i);
                qDebug()<<i<<" "<<rows->size()<<" "<<currentRow;
                setActive(rows->at(currentRow-1)->at(0));
            } else {
                rows->removeAt(i);
            }
            break;
        }
    }
}

void KeyControllableMenu::setStyleSheets(QString selected,QString unselected, QString inactiveSelected) {
    this->selectedStyleSheet=selected;
    this->unSelectedStyleSheet=unselected;
    this->inactiveSelectedStyleSheet=inactiveSelected;
}

Button * KeyControllableMenu::getCurrentButton() {
    if(!rows||rows->size()==0||rows->size()<=currentRow) {
        return NULL;
    }
    if(rows->size()<=currentRow) {
        currentRow=0;
        currentColumn=0;
        setActive(rows->at(currentRow)->at(currentColumn));
    }
    else if(rows->at(currentRow)->size()<=currentColumn) {
        currentColumn=0;
        setActive(rows->at(currentRow)->at(currentColumn));
    }
    return rows->at(currentRow)->at(currentColumn);
}

void KeyControllableMenu::show() {
    grabKeyboard();
    qDebug()<<"grabbed the keyboard";
    QWidget::show();
}

void KeyControllableMenu::clearRows() {
    rows->clear();
}

void KeyControllableMenu::activate() {
    if(getCurrentButton()) {
        getCurrentButton()->setStyleSheet(selectedStyleSheet);
    }
    active=true;
    grabKeyboard();
}

void KeyControllableMenu::deactivate() {
    getCurrentButton()->setStyleSheet(inactiveSelectedStyleSheet);
    active=false;
    releaseKeyboard();
}

void KeyControllableMenu::addButtonBefore(Button *toAdd, Button *otherButton) {
    for(int i=0; i<rows->size(); i++) {
        if(rows->at(i)->contains(otherButton)) {
            ButtonList * list=new ButtonList();
            list->append(toAdd);
            connect(toAdd, SIGNAL(mouseEntered(Button*)), this, SLOT(buttonEntered(Button*)));
            connect(toAdd, SIGNAL(clicked()), this,  SLOT(buttonSelected()));
            connect(toAdd,SIGNAL(rightClicked()),this,SLOT(buttonRightClicked()));
            toAdd->setStyleSheet(unSelectedStyleSheet);
            rows->insert(i,list);
            if(i>=currentRow) {
                currentRow++;
            }
            break;
        }
    }
}


void KeyControllableMenu::displayPopup(QWidget * widget, QWidget * relativeTo, int x, int y) {

    if(x+widget->width()>relativeTo->width()) {
        qDebug() <<"moving horizontally from "<<x<<" to "<<relativeTo->width()-widget->width();
        x=relativeTo->width()-widget->width();
    }
    if(y+widget->height()>relativeTo->height()) {
        qDebug() <<"moving vertically from "<<y<<" to "<<relativeTo->height()-widget->height();
        qDebug()<<"parent's height "<<relativeTo->height();
        qDebug()<<"widget's height "<<widget->height();
        y=relativeTo->height()-widget->height();
    }
    //y+=100;
    qDebug()<<"go go go to "<<QString::number(x)<<" "<<QString::number(y);
    widget->move(x,y);
    widget->show();
}

void KeyControllableMenu::displayPopup(QWidget * widget, int x, int y) {
    QWidget * parent=qobject_cast<QWidget *>(widget->parent());
    if(parent) {
        displayPopup(widget,parent,x,y);
    }
    /*if(x+widget->width()>parent->width()) {
        qDebug() <<"moving horizontally from "<<x<<" to "<<parent->width()-widget->width();
        x=parent->width()-widget->width();
    }
    if(y+widget->height()>parent->height()) {
        qDebug() <<"moving vertically from "<<y<<" to "<<parent->height()-widget->height();
        y=parent->height()-widget->height();
    }
    widget->move(QPoint(x,y));
    widget->show();*/
}


void KeyControllableMenu::buttonRightClicked() {

}

Button * KeyControllableMenu::findButton(QObject *item) {
    for(int i=0; i<rows->size(); i++) {
        for(int j=0; j<rows->at(i)->size(); j++) {
            if(rows->at(i)->at(j)->getItem()==item) {
                return rows->at(i)->at(j);
            }
        }
    }
    return NULL;
}

void KeyControllableMenu::setCircularHorizontally(bool circular) {
    isCircularHorizontally=circular;
}

void KeyControllableMenu::setCircularVertically(bool circular) {
    isCircularVertically=circular;
}



void KeyControllableMenu::wheelEvent(QWheelEvent * event) {
    if(!active) {
        return;
    }
    qDebug() <<"wheel event "<<event->delta();
    int steps=event->delta()/120;
    if(steps>0) {
        for(int sum=0; sum<steps; sum++) {
            keyPressEvent(new QKeyEvent(QEvent::KeyPress,KeyBindings::upKey[0],(Qt::KeyboardModifier)KeyBindings::upKey[1]));
        }
    }
    else {
        for(int sum=0; sum>steps; sum--) {
            keyPressEvent(new QKeyEvent(QEvent::KeyPress,KeyBindings::downKey[0],(Qt::KeyboardModifier)KeyBindings::downKey[1]));
        }
    }
}
